function preproc(subject, grad, condition)
% Performs preprocessing:
% - removes artifacttrials in cfg_rejectArtifact.trl (stored in  subject.subjectDir/subject.subjID_cfg_rejectArtifact.mat)
% - resamples to 300 Hz
% - denoises with 3rd order gradient
% - converts to planar
% subject: struct with subject info which should at least include the
% fields subjID, subjectDir, allChannels (all channels but the rejected
% ones) and resampledData (path to the raw dataset)
% grad: use 'planar' or 'axial' gradient
% data is stored in subject.subjectDir/subject.subjID_data

    % required time ~8.3 minutes; required memory ~5.3GB
    eval(['load ' subject.subjectDir, '/', subject.subjID, '_', condition, '_cfg_rejectArtifact.mat cfg_rejectArtifact; ']);
    cfg                 = [];
    cfg.dataset         = subject.resampledData;
    cfg.trl             = cfg_rejectArtifact.trl;
    cfg.channel         = subject.allChannels;
    cfg.dftfilter       = 'no'; %should be filtered out already by the first resampling step?
    cfg.demean          = 'no'; %baseline correction
    cfg.detrend         = 'no'; %linear trend removal per trial
    cfg.lpfilter        = 'yes';
    cfg.lpfreq          = 150;
    cfg.datatype        = 'continuous';
    data_preproc = ft_preprocessing(cfg);
    
    save([subject.subjectDir,'/' subject.subjID, '_', condition, '_data'],'data_preproc', '-v7.3')

    % resample
    cfg                 = [];
    cfg.resamplefs      = 300;
    cfg.detrend         = 'no';
    data_resampled      = ft_resampledata(cfg, data_preproc);
    
    save([subject.subjectDir,'/' subject.subjID, '_', condition, '_data'],'data_resampled','-append', '-v7.3')
    clear data_preproc;

    % denoise meg using the 3rd gradient
    cfg                         = [];
    cfg.gradient                = 'G3BR';
    cfg.trials                  = 'all';
    data_denoised               = ft_denoise_synthetic(cfg, data_resampled);

    save([subject.subjectDir,'/' subject.subjID, '_', condition, '_data'],'data_denoised','-append', '-v7.3')
    clear data_resampled
    
    if strcmp(grad, 'planar')
        % convert to planar gradient
        cfg                 = [];
        cfg.method          = 'template'; %NOTE: template may change in fieldtrip. Use ft_neighbourplot to view. Can specify template with cfg.template. Make sure the specified template does not change though.
        neighbours          = ft_prepare_neighbours(cfg, data_denoised);

        cfg                 = [];
        cfg.planarmethod    = 'sincos'; %requires neighbours
        cfg.neighbours      = neighbours;
        data_planar         = ft_megplanar(cfg, data_denoised);

        cfg                 = [];
        data_combinedPlanar = ft_combineplanar(cfg, data_planar);

        % save preprocessed data to disk
        data = data_combinedPlanar; %don't think you want to use the uncombined planar?
    elseif strcmp(grad, 'axial')
        data = data_denoised;
        clear data_denoised;
    else
        error('Unknown gradient type. Please specify gradient as axial or planar.');
    end
    
    save([subject.subjectDir,'/' subject.subjID, '_', condition, '_data'],'data*','-append', '-v7.3')
end
